package com.d2.framework.aspectj;

import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.d2.common.domain.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.d2.common.annotation.Dict;
import com.d2.modules.system.util.DaoUtils;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


@Aspect
@Component
@Slf4j
public class DictAspect {

    @Autowired
    private ObjectMapper mapper;

    // 定义切点Pointcut
    @Pointcut("execution(public * com.d2.modules..*.*Controller.*(..))")
    public void executeService() {

    }

    @Around("executeService()")
    public Object doAround(ProceedingJoinPoint pjp) throws Throwable {

        //controller中的方法执行前
        //...
        Object result = pjp.proceed();//执行controller中的方法
        try {
            return this.parseDictText(result);
        } catch (Exception e) {

        }
        return result;
    }

    private Object parseDictText(Object result) throws IOException {
        List data;
        if (result instanceof Result) {
            boolean flag = false;
            Object retData = ((Result) result).getData();
            if (retData instanceof IPage) {
                data = ((IPage) ((Result<?>) result).getData()).getRecords();
            } else if (retData instanceof List) {
                data = (List) ((Result<?>) result).getData();
            } else if (retData instanceof String) {
                return result;
            } else if (retData instanceof Integer) {
                return result;
            } else if (retData instanceof Long) {
                return result;
            } else if (retData instanceof BigDecimal) {
                return result;
            } else if (retData instanceof Float) {
                return result;
            } else if (retData instanceof Double) {
                return result;
            } else {
                data = new ArrayList<>();
                data.add(((Result<?>) result).getData());
                flag = true;
            }
            for (int i = 0; i < data.size(); i++) {
                Object o = data.get(i);
                Map obj = mapper.readValue(mapper.writeValueAsString(o), Map.class);

                data.set(i, obj);

                Field[] fields = ReflectUtil.getFields(o.getClass());

                for (Field field : fields) {
                    Dict annotation = field.getAnnotation(Dict.class);
                    if (annotation != null) {
                        obj.put(field.getName() + "Str", null);
                        Object fieldValue = obj.get(field.getName());
                        obj.put(field.getName() + "Str", DaoUtils.translate(annotation, fieldValue));
                    }
                }
            }
            if (flag && !data.isEmpty()) {
                ((Result) result).setData(data.get(0));
            }
        }
        return result;
    }
}
